/*
Copyright (c) 2025 HeZongLun
NahidaProject is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/

#include "ThreadPool.h"

void NahidaProject::ThreadPool::Queue::ThreadPool::Start(size_t num_threads) {
	_threads.reserve(num_threads);
	for (auto i = 0u; i < num_threads; ++i) {
		_threads.emplace_back([=] {
			while (true) {
				task_t task;
				{
					std::unique_lock<std::mutex> lock(_mutex);
					_event.wait(lock, [this] { return _stopping || !_tasks.empty(); });

					if (_stopping && _tasks.empty()) { break; }

					task = std::move(_tasks.front());
					_tasks.pop();
				}
				std::invoke(task);
			}
			});
	}
}

void NahidaProject::ThreadPool::Queue::ThreadPool::Stop() noexcept {
	{
		std::unique_lock<std::mutex> lock(_mutex);
		_stopping = true;
	}

	_event.notify_all();
	for (auto& thread : _threads) {
		if (thread.joinable()) {
			thread.join();
		}
	}
}

void NahidaProject::ThreadPool::SafeQueue::ThreadPool::Start(size_t num_threads) {
	_threads.reserve(num_threads);
	for (auto i = 0u; i < num_threads; ++i) {
		_threads.emplace_back([=] {
			while (true) {
				task_t task;
				{
					std::unique_lock<std::mutex> lock(_mutex);
					_event.wait(lock, [this] {
						return _stopping || !_tasks.Empty();
						});

					if (_stopping && _tasks.Empty()) {
						break;
					}
					task = std::move(*(_tasks.Pop()));
				}
				std::invoke(task);
			}
			});
	}
}

void NahidaProject::ThreadPool::SafeQueue::ThreadPool::Stop() noexcept {
	{
		std::unique_lock<std::mutex> lock(_mutex);
		_stopping = true;
	}

	_event.notify_all();

	for (auto& thread : _threads) {
		if (thread.joinable()) {
			thread.join();
		}
	}
}